package com.example.demo.pdf.service;

import com.example.demo.pdf.PdfDto;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zjq
 * @version 创建时间：2022-4-6 10:00:58
 */
@Service
public class PdfService2Impl implements PdfService2 {

    // 模板路径
    @Value("${pdf-path}")
    private String templatePath;

    //controller 调的这个方法 ---- 此方法适用单个文件
    @Override
    public void fillPdf(HttpServletRequest req, HttpServletResponse resp) {
        // 往里面塞数据
        Map<String, String> map = new HashMap();
        map.put("name", "张三张三"); //这里文本超出，会自动调整文本域
        map.put("creatdate", "2018年1月1日");
        map.put("weather", "晴朗");

        Map<String, String> map2 = new HashMap();
        map2.put("2a", "晴朗第二页晴朗第二页晴朗第二页晴朗第二页晴朗第二页晴朗第二页晴朗第二页晴朗第二页晴朗第二页晴朗第二页");
        map2.put("2b", "");
        map2.put("2c", "");

        Map<String, String> imgmap = new HashMap();
        imgmap.put("img", "G:\\java\\xing.jpg");

        Map<String, String> map3 = new HashMap();
        map3.put("b", "晴朗第三页");

        Map<String, Object> o = new HashMap();
        o.put("page1", map);
        o.put("page2", map2);
        o.put("imgmap", imgmap);
        o.put("page3", map3);
        pdfout(req, resp, o);
    }

    // 利用模板生成pdf----把流放入内存中，不会生成临时文件---此方法适用单个文件
    public void pdfout(HttpServletRequest req, HttpServletResponse resp, Map<String, Object> o) {
        PdfReader reader = null;
        ByteArrayOutputStream out = null;
        ByteArrayOutputStream bos = null;
        PdfStamper stamper;
        try {

            BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            out = new ByteArrayOutputStream();// 输出流
            reader = new PdfReader(templatePath);// 读取pdf模板，模板路径
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();

            // 文字类的内容处理
            Map<String, String> datamap = (Map<String, String>) o.get("page1");
            form.addSubstitutionFont(bf);
            for (String key : datamap.keySet()) {
                String value = datamap.get(key);
                form.setField(key, value);
                //自动调整文本域的字体的大小
                form.setFieldProperty(key, "textsize", checkAddrLength(datamap.get(key), key, form), null);
            }

            Map<String, String> datamap2 = (Map<String, String>) o.get("page2");
            for (String key : datamap2.keySet()) {
                String value = datamap2.get(key);
                form.setField(key, value);
            }

            //图片类的内容处理
            Map<String, String> imgmap = (Map<String, String>) o.get("imgmap");
            for (String key : imgmap.keySet()) {
                String value = imgmap.get(key);
                String imgpath = value;
                int pageNo = form.getFieldPositions(key).get(0).page;
                Rectangle signRect = form.getFieldPositions(key).get(0).position;
                float x = signRect.getLeft();
                float y = signRect.getBottom();
                //根据路径读取图片
                Image image = Image.getInstance(imgpath);
                //获取图片页面
                PdfContentByte under = stamper.getOverContent(pageNo);
                //图片大小自适应
                image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                //添加图片
                image.setAbsolutePosition(x, y);
                under.addImage(image);
            }

            Map<String, String> datamap3 = (Map<String, String>) o.get("page3");
            for (String key : datamap3.keySet()) {
                String value = datamap3.get(key);
                form.setField(key, value);
            }

            stamper.setFormFlattening(true);// 如果为false，生成的PDF文件可以编辑，如果为true，生成的PDF文件不可以编辑
            stamper.close();

            Document doc = new Document();
            PdfCopy copy = new PdfCopy(doc, out);
            doc.open();

            PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
            PdfImportedPage importPage2 = copy.getImportedPage(new PdfReader(bos.toByteArray()), 2);
            PdfImportedPage importPage3 = copy.getImportedPage(new PdfReader(bos.toByteArray()), 3);

            copy.addPage(importPage);
            copy.addPage(importPage2);
            copy.addPage(importPage3);
            doc.close();

            // 设置response的Header
            String fileName = "demoWithoutFile";
            String fileNameURL = java.net.URLEncoder.encode(fileName + ".pdf", "UTF-8");

            resp.setHeader("content-disposition",
                    "attachment;filename=" + fileNameURL + ";" + "filename*=utf-8''" + fileNameURL);
            resp.setContentType("application/pdf");
            OutputStream toClient = new BufferedOutputStream(resp.getOutputStream());
            toClient.write(out.toByteArray());
            toClient.flush();
            toClient.close();

        } catch (IOException e) {
            System.out.println(e);
        } catch (DocumentException e) {
            System.out.println(e);
        } finally {
            // 关闭流
            try {
                reader.close();
                out.close();
                bos.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }


    // 利用模板生成pdf，返回文件输出流----塞入模拟数据
    @Override
    public ByteArrayOutputStream fillPdf(PdfDto dto) {
        // 往里面塞数据
        Map<String, String> map = new HashMap();
        map.put("name", "张三");
        map.put("creatdate", "2018年1月1日");
        map.put("weather", "晴朗");

        Map<String, String> map2 = new HashMap();
        map2.put("a", "晴朗第二页");

        Map<String, String> map3 = new HashMap();
        map3.put("b", "晴朗第三页");

        Map<String, Object> o = new HashMap();
        o.put("page1", map);
        o.put("page2", map2);
        o.put("page3", map3);

        return pdfout(o);
    }

    // 利用模板生成pdf，返回文件输出流
    public ByteArrayOutputStream pdfout(Map<String, Object> o) {
        PdfReader reader = null;
        ByteArrayOutputStream out = null;
        ByteArrayOutputStream bos = null;
        PdfStamper stamper;
        try {

            BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            out = new ByteArrayOutputStream();// 输出流
            reader = new PdfReader(templatePath);// 读取pdf模板
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();

            // 文字类的内容处理
            Map<String, String> datamap = (Map<String, String>) o.get("page1");
            form.addSubstitutionFont(bf);
            for (String key : datamap.keySet()) {
                String value = datamap.get(key);
                form.setField(key, value);
            }

            Map<String, String> datamap2 = (Map<String, String>) o.get("page2");
            for (String key : datamap2.keySet()) {
                String value = datamap2.get(key);
                form.setField(key, value);
            }

            Map<String, String> datamap3 = (Map<String, String>) o.get("page3");
            for (String key : datamap3.keySet()) {
                String value = datamap3.get(key);
                form.setField(key, value);
            }

            stamper.setFormFlattening(true);// 如果为false，生成的PDF文件可以编辑，如果为true，生成的PDF文件不可以编辑
            stamper.close();

            Document doc = new Document();
            PdfCopy copy = new PdfCopy(doc, out);
            doc.open();

            PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
            PdfImportedPage importPage2 = copy.getImportedPage(new PdfReader(bos.toByteArray()), 2);
            PdfImportedPage importPage3 = copy.getImportedPage(new PdfReader(bos.toByteArray()), 3);

            copy.addPage(importPage);
            copy.addPage(importPage2);
            copy.addPage(importPage3);
            doc.close();

        } catch (IOException e) {
            System.out.println(e);
        } catch (DocumentException e) {
            System.out.println(e);
        } finally {
            // 关闭流
            try {
                reader.close();
                out.close();
                bos.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return out;
    }


    // 利用模板生成pdf---临时文件的形式，适用压缩包内容下载
    @Override
    public void pdfList2(Map<String, Object> o, String newPDFPath) {
        File file = new File(newPDFPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        // 生成的新文件路径
        newPDFPath += o.get("filename").toString() + ".pdf";

        PdfReader reader;
        FileOutputStream out;
        ByteArrayOutputStream bos;
        PdfStamper stamper;
        try {
            BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            out = new FileOutputStream(newPDFPath);// 输出流
            reader = new PdfReader(templatePath);// 读取pdf模板
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();

            // 文字类的内容处理
            Map<String, String> datamap = (Map<String, String>) o.get("page1");
            form.addSubstitutionFont(bf);
            for (String key : datamap.keySet()) {
                String value = datamap.get(key);
                form.setField(key, value);
            }

            Map<String, String> datamap2 = (Map<String, String>) o.get("page2");
            for (String key : datamap2.keySet()) {
                String value = datamap2.get(key);
                form.setField(key, value);
            }
            //图片类的内容处理
            Map<String, String> imgmap = (Map<String, String>) o.get("imgmap");
            for (String key : imgmap.keySet()) {
                String value = imgmap.get(key);
                String imgpath = value;
                int pageNo = form.getFieldPositions(key).get(0).page;
                Rectangle signRect = form.getFieldPositions(key).get(0).position;
                float x = signRect.getLeft();
                float y = signRect.getBottom();
                //根据路径读取图片
                Image image = Image.getInstance(imgpath);
                //获取图片页面
                PdfContentByte under = stamper.getOverContent(pageNo);
                //图片大小自适应
                image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                //添加图片
                image.setAbsolutePosition(x, y);
                under.addImage(image);
            }

            Map<String, String> datamap3 = (Map<String, String>) o.get("page3");
            for (String key : datamap3.keySet()) {
                String value = datamap3.get(key);
                form.setField(key, value);
            }
            Map<String, String> datamap4 = (Map<String, String>) o.get("page4");
            for (String key : datamap4.keySet()) {
                String value = datamap4.get(key);
                form.setField(key, value);
            }

            stamper.setFormFlattening(true);// 如果为false，生成的PDF文件可以编辑，如果为true，生成的PDF文件不可以编辑
            stamper.close();
            Document doc = new Document();
            PdfCopy copy = new PdfCopy(doc, out);
            doc.open();

            PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
            PdfImportedPage importPage2 = copy.getImportedPage(new PdfReader(bos.toByteArray()), 2);
            PdfImportedPage importPage3 = copy.getImportedPage(new PdfReader(bos.toByteArray()), 3);
            PdfImportedPage importPage4 = copy.getImportedPage(new PdfReader(bos.toByteArray()), 4);

            copy.addPage(importPage);
            copy.addPage(importPage2);
            copy.addPage(importPage3);
            copy.addPage(importPage4);
            doc.close();

        } catch (IOException e) {
            System.out.println(e);
        } catch (DocumentException e) {
            System.out.println(e);
        }

    }

    //模拟数据填入
    @Override
    public Map<String, Object> fillData(String a, String b) {
        String filename = "";
        // 往里面塞数据
        Map<String, String> map = new HashMap();
        map.put("name", "张三张三111"); //这里文本超出，会自动调整文本域
        map.put("creatdate", "2018年1月1日");
        map.put("weather", "晴朗");

        Map<String, String> map2 = new HashMap();
        map2.put("a", "晴朗第二页");

        Map<String, String> imgmap = new HashMap();
        imgmap.put("img", "I:\\java\\xing.jpg");

        Map<String, String> map3 = new HashMap();
        map3.put("b", "晴朗第三页");

        Map<String, Object> o = new HashMap();
        o.put("page1", map);
        o.put("page2", map2);
        o.put("imgmap", imgmap);
        o.put("page3", map3);
        o.put("filename", filename);//文件名称
        return o;
    }


    //此方法调整文本域
    public float checkAddrLength(String addr, String fileName, AcroFields form) throws IOException, DocumentException {
        BaseFont baseFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        float fontSize = 12f;
        Rectangle position = form.getFieldPositions(fileName).get(0).position;
        float textBoxWidth = position.getWidth();
        /*文本框高度*/
        float textBoxHeight = position.getHeight();
        /*文本单行行高*/
        float ascent = baseFont.getFontDescriptor(baseFont.ASCENT, fontSize);
        /*baseFont渲染后的文字宽度*/
        float textWidth = baseFont.getWidthPoint(addr, fontSize);

        /*文本框高度只够写一行，并且文字宽度大于文本框宽度，则缩小字体*/
        if (textBoxHeight < ascent * 1.6) {
            while (textWidth > textBoxWidth) {
                fontSize--;
                textWidth = baseFont.getWidthPoint(addr, fontSize);
            }
        }
        return fontSize;
    }
}
